package com.fingard.dsp.bank.directbank.ccb02;


import com.ccb.wlpt.encrypt.CCBWLPTMessageCoder;
import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.ccb02.util.DESedeCoder;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XmlTextWriter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class CCB02Base extends DirectBase implements ITcpClient {

    private static TransIDHelper idHelper = new TransIDHelper(1, 999);

    protected String getQryTransID() {
        Date tmpDateNow = new Date();
        return Format.DateTime12Year2Format.format(tmpDateNow) + idHelper.getNextIDStr();
    }

    protected void writeCommonHeader(XmlTextWriter xmlWriter, CCB02Header p_bankHeader) throws Exception {
        if (StringHelper.isNullOrEmpty(p_bankHeader.REQUEST_SN)) {
            throw new Exception("未赋值REQUEST_SN");
        }
        if (StringHelper.isNullOrEmpty(p_bankHeader.TX_CODE)) {
            throw new Exception("未赋值TX_CODE");
        }
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"gb2312\" standalone=\"yes\" ?>");
        xmlWriter.writeStartElement("TX");
        xmlWriter.writeElementString("REQUEST_SN", p_bankHeader.REQUEST_SN);
        xmlWriter.writeElementString("CUST_ID", bankFront.org);//客户号
        xmlWriter.writeElementString("USER_ID", bankFront.operator);//操作员号
        xmlWriter.writeElementString("PASSWORD", bankFront.loginPasswd);
        xmlWriter.writeElementString("TX_CODE", p_bankHeader.TX_CODE);
        xmlWriter.writeElementString("LANGUAGE", "CN");
    }

    protected String getCharset() {
        return getBankConfig().getCharset("GBK");
    }

    protected String[] sendToBank(String p_reqStr) throws Exception {
        return sendToBank(p_reqStr, "", "");
    }

    protected String[] sendToBank(String p_reqStr, String transType, String commandCode) throws Exception {
        String[] retStr = new String[]{"", ""};
        WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP + ":" + bankFront.serverPort);

        if (StringHelper.hasAnyChar(transType) && StringHelper.hasAnyChar(commandCode)) {
            //后置挡板
            this.detailSimulateForBank(bankFront.bankCode, transType, commandCode, p_reqStr, retStr);
            if (retStr[1].length() > 0) {
                return retStr;
            }
        }

        //发送银行前置
        TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.serverPort), this);
        String tmpCharset = getCharset();
        byte[] tmpBytesBody = p_reqStr.getBytes(tmpCharset);

        WriteBankLogStep2(p_reqStr);
        if (getBankConfig().getValueAsString("encryptFlag").equals("true")) {
            String saltKey = getBankConfig().getValueAsString("sBase64Key");
            if (StringHelper.isNullOrEmpty(saltKey)) {
                throw new RuntimeException("config.xml文件中encryptFlag为true时，sBase64Key不得为空，可与银行客户经理确认密钥串信息");
            }
            CCBWLPTMessageCoder ccbwlptMessageCoder = new CCBWLPTMessageCoder(saltKey, "GB18030");
            byte[] bytes = p_reqStr.getBytes(Charset.forName("GB18030"));//转成gb18030格式的字节码
            String reqStr = ccbwlptMessageCoder.encrypt(new String(bytes, "GB18030"), "GB18030");
            //      tmpBytesBody = DESedeCoder.encrypt(tmpBytesBody, getBankConfig().getValueAsString("sBase64Key"));
            String repBody = sendSocketRequest(bankFront.serverIP, Integer.valueOf(bankFront.serverPort), reqStr);
            WriteBankLogLn("银行返回的原始数据为;" + repBody);
            retStr[1] = new String(ccbwlptMessageCoder.decrypt(repBody, "GB18030"));
            byte[] bytes4 = retStr[1].getBytes(Charset.forName("UTF-8"));
            retStr[1] = new String(bytes4, "UTF-8");
            WriteBankLogStep3("银行返回的数据为;" + retStr[1]);
        } else {
            TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpBytesBody);
            retStr[0] = tmpReceiver.connState;
            if (tmpReceiver.recBytes != null) {
                if (getBankConfig().getValueAsString("encryptFlag").equals("true")) {
                }
                retStr[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, tmpCharset);
                WriteBankLogStep3(retStr[1]);
            } else {
                retStr[1] = tmpReceiver.getConnMsg();
            }
            if (!tmpReceiver.isCompleted) {
                WriteBankLogLn(tmpReceiver.getConnMsg());
            }
        }
        //模拟
        //retStr[0] = "";
        //retStr[1] = FileHelper.readFileText("D:\\Workspaces\\FilesForDevelop\\BankPort\\CCB02\\模拟用\\1.txt", "gbk");
        //
        return retStr;
    }

    public String sendSocketRequest(String ipAddress, int nPort, String sRequest) {
        String sResult = "";
        try {
            Socket socket = new Socket(ipAddress, nPort);
            BufferedReader ins = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GB18030"));
            PrintWriter outs = new PrintWriter(socket.getOutputStream());

            outs.print(sRequest);
            outs.flush();
            socket.shutdownOutput();

            String sLine = null;
            StringBuffer sb = new StringBuffer();
            while ((sLine = ins.readLine()) != null) {
                sb.append(sLine);
            }

            ins.close();
            outs.close();
            socket.close();

            return sb.toString();

        } catch (NumberFormatException e) {
            sResult = e.getMessage();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            sResult = e.getMessage();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            sResult = e.getMessage();
        }
        return sResult;
    }

    public void getContentLength(TcpReceiver p_receiver) throws Exception {
        if (p_receiver.contentLength == -1) {
            String tmpCharset = getCharset();
            String tmpRecNow = new String(p_receiver.recBytes, 0, p_receiver.readedLength, tmpCharset);
            if (tmpRecNow.indexOf("</TX>") >= 0) {
                p_receiver.contentLength = p_receiver.readedLength;
                p_receiver.contentStartIndex = 0;
            }
        }
    }

    protected String codeToAscii(String p_Code) throws Exception {
        boolean useDspReqSeqID = getBankConfig().getValueAsBool("useDspReqSeqID");
        if (useDspReqSeqID) {
            byte[] Bytes = p_Code.getBytes(getCharset());
            StringBuilder tmpReturnCode = new StringBuilder();

            for (byte b : Bytes) {
                if ((short) b <= 57 && (short) b >= 48) {
                    tmpReturnCode.append(String.valueOf((short) b - 48));
                } else {
                    tmpReturnCode.append("0" + String.valueOf((short) b));
                }
            }
            if (tmpReturnCode.toString().length() > 16) {
                return tmpReturnCode.toString().substring(tmpReturnCode.toString().length() - 16);
            } else {
                return tmpReturnCode.toString();
            }
        } else {
            return p_Code;
        }
    }

    //上送格式为json格式
    protected String[] sendToATS(String jsonData) throws Exception {
        String[] retStr = new String[]{"", ""};
        WriteBankLogLn("2.提交ATS的地址：" + FGBiz.dspCenter.dspSet.receiptPushServerUrl);
        //发送银行前置
        WebRequest tmpRequest = new WebRequest(FGBiz.dspCenter.dspSet.receiptPushServerUrl);
        tmpRequest.setConnectTimeout(60000);
        tmpRequest.setRequestProperty("connection", "Close");
        tmpRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        String charsetName = getCharset();
        WriteBankLogLn("3.推送给ATS的json数据" + jsonData);
        byte[] tmpWriteBytes = jsonData.getBytes(charsetName);
        retStr = tmpRequest.upload(tmpWriteBytes, charsetName);
        WriteBankLogLn("4.返回的数据" + retStr[1]);

        return retStr;
    }

    /**
     * 过滤返回不匹配的应答信息
     *
     * @param busiType 1-出票 2-承兑 3-收票 4-背书转让 5-质押 6-解质押 7-出票保证 8-承兑保证 9-背书保证 10-贴现 11-回购式贴现赎回 12-提示付款 13-追索 14-同意清偿
     * @param bktype2
     * @param billType 1 银承 2 商承
     * @return
     * @throws Exception
     */
    protected boolean checkBkType(int busiType, String queryType, String bktype2, String billType) throws Exception {
        boolean flag = false;
        switch (busiType) {
            case 2:
                if ("4".equals(bktype2)) {
                    flag = true;
                }
                break;
            case 3:
                if ("0".equals(bktype2)) {
                    flag = true;
                }
                break;
            case 4:
                if ("5".equals(bktype2)) {
                    flag = true;
                }
                break;
            case 5:
                if ("9".equals(bktype2) && "2".equals(billType)) {
                    flag = true;
                }
                break;
            case 6:
                if ("10".equals(bktype2)) {
                    flag = true;
                }
                break;
            case 7:
                if ("1".equals(bktype2)) {
                    flag = true;
                }
                break;
            case 8:
                if ("2".equals(bktype2)) {
                    flag = true;
                }
                break;
            case 9:
                if ("3".equals(bktype2)) {
                    flag = true;
                }
                break;
            case 11:
                if ("11".equals(bktype2)) {
                    flag = true;
                }
                break;
            case 12:
                if ("6".equals(bktype2)) {
                    flag = true;
                }
                break;
//            case 13:if("7".equals(bktype2)){flag=true;} break;
            case 14:
                if ("8".equals(bktype2) && "2".equals(queryType)) {
                    flag = true;
                } else if ("7".equals(bktype2) && "1".equals(queryType)) {
                    flag = true;
                }
                break;
            default:
                flag = false;
        }
        return flag;
    }

    /**
     * 票据背面信息查询业务转换
     * 交易类型代码 2  承兑 3  收票 4  撤票 10  背书转让 11  贴现 12  回购式贴现赎回 13  转贴现 14  回购式转贴现赎回 15  再贴现
     * 16  回购式再贴现赎回 25  央行卖出商业汇票 17  保证 18  质押 19  质押解除 20  提示付款 21  逾期提示付款 22  追索 23  追索同意清偿
     *
     * @return
     */
    protected String getTransCode(String billType) {
        String transCode = "";
        if (!StringHelper.isNullOrEmpty(billType)) {
            switch (Integer.parseInt(billType)) {
                case 0:
                    transCode = "10";
                    break;//背书
                case 1:
                    transCode = "17";
                    break;//保证
                case 2:
                    transCode = "18";
                    break;//18  质押
                case 3:
                    transCode = "11";
                    break;//买断式贴现
                case 4:
                    transCode = "11";
                    break;//回购式贴现
                case 5:
                    transCode = "12";
                    break;//回购式贴现赎回
                case 6:
                    transCode = "13";
                    break;//买断式转贴现
                case 7:
                    transCode = "13";
                    break;//回购式转贴现
                case 8:
                    transCode = "14";
                    break;//14  回购式转贴现赎回
                case 9:
                    transCode = "15";
                    break;//买断式再贴现
                case 10:
                    transCode = "15";
                    break;//回购式再贴现
                case 11:
                    transCode = "16";
                    break;//16  回购式再贴现赎回
                case 12:
                    transCode = "25";
                    break;//25  央行卖出商业汇票
                case 13:
                    transCode = "20";
                    break;//提示付款
                //case 13:transCode="21";break;//逾期提示付款
                case 14:
                    transCode = "22";
                    break;//追索
                case 15:
                    transCode = "22";
                    break;//再追索
                //case 020006:transCode="23";break;//追索同意清偿
                default:
                    transCode = "";
            }
        }
        return transCode;
    }

    public String antiTransferStr(String tmpReqInfo) {
        // 针对建行回单编号特殊字符处理
        //CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)CON", "101");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)PRN", "102");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)AUX", "103");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)NUL", "104");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)COM1", "2011");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)COM2", "2012");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)COM3", "2013");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)COM4", "2014");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)COM5", "2015");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)COM6", "2016");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)COM7", "2017");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)COM8", "2018");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)COM9", "2019");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)LPT1", "3011");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)LPT2", "3012");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)LPT3", "3013");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)LPT4", "3014");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)LPT5", "3015");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)LPT6", "3016");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)LPT7", "3017");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)LPT8", "3018");
        tmpReqInfo = tmpReqInfo.replaceAll("(?i)LPT9", "3019");

        return tmpReqInfo;
    }

    // 根据年月求每个月的月末日期
    public static String dateConvert(Date date) throws ParseException {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int days = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        c.add(Calendar.DAY_OF_MONTH, days - 1);
        Date date2 = c.getTime();
        String monthend = new SimpleDateFormat("yyyyMMdd").format(date2);
        return monthend;
    }
}